/*

The following two functions let you convert
between a color and an ASCII string suitable
for writing to defaults or storing in text documents.

Call convertColorToString() with a color and a
string at least COLORSTRINGLENGTH long. Later
call getColorFromString() with a string obtained
from convertColorToString() and a pointer to a
color; if the function returns YES a color was
successfully parsed from the string.

 void convertColorToString (NXColor color, char *str)
 BOOL getColorFromString (const char *str, NXColor *color)

The following two functions let you read/write colors
in the defaults database of the application.

 void writeColorToDefaults (NXColor color, const char *defaultName)
 BOOL readColorFromDefaults (const char *defaultName, NXColor *color)

Written by Ali Ozer, 5/29/92.

You may freely copy, distribute and reuse the code in this example.
NeXT disclaims any warranty of any kind, expressed or implied,
as to its fitness for any particular use.

*/

#import <appkit/appkit.h>
#import "colorAsAscii.h"

void writeColorToDefaults (NXColor color, const char *defaultName)
{
    char str[1024];
    convertColorToString(color, str);
    NXWriteDefault([NXApp appName], defaultName, str);
}

BOOL readColorFromDefaults (const char *defaultName, NXColor *color)
{
    const char *tmp = NXGetDefaultValue([NXApp appName], defaultName);
    return (tmp && getColorFromString (tmp, color)) ? YES : NO;
}

void convertColorToString (NXColor color, char *str)
{
    static const char hexDigits[16] = "0123456789ABCDEF";
    NXStream *colorStream = NXOpenMemory(NULL, 0, NX_READWRITE);
    NXTypedStream *ts = colorStream ? NXOpenTypedStream(colorStream, NX_WRITEONLY) : NULL;
    
    if (ts) {
	int i, pos;
	NXWriteColor(ts,color);
	NXCloseTypedStream(ts);
	pos = NXTell(colorStream);
    	NXSeek(colorStream, 0, NX_FROMSTART);
	i = 0;
	while (i++ < pos) {
	    unsigned char ch = NXGetc(colorStream);
	    *str++ = hexDigits[(ch>>4) & 0xF];
	    *str++ = hexDigits[ch & 0xF];
        }
    }
    *str = 0;
    if (colorStream) NXCloseMemory (colorStream, NX_FREEBUFFER);
}

#define BAD 255
#define HEX(c) (((c)>='A' && (c)<='F') ? ((c)-'A'+10): (((c)>='0'&&(c)<='9') ? ((c)-'0') : BAD))

BOOL getColorFromString (const char *str, NXColor *color)
{
    unsigned char binaryBuffer[COLORSTRINGLENGTH];
    NXStream *stream;
    NXTypedStream *ts;
    int len = 0;
    BOOL success = NO;
    
    while (*str) {
	unsigned char first = HEX(str[0]), second = HEX(str[1]);
	if (first == BAD || second == BAD) return NO;	
	binaryBuffer[len] = (first << 4) + second;
	str += 2;
	len++;
    }
    
    if (len &&
	(stream = NXOpenMemory(binaryBuffer, len, NX_READONLY)) &&
    	(ts = NXOpenTypedStream(stream, NX_READONLY))) {
	NX_DURING
	    *color = NXReadColor(ts);
	    success = YES;
	NX_HANDLER
	NX_ENDHANDLER	 
    }
    if (ts) NXCloseTypedStream(ts);
    if (stream) NXCloseMemory(stream, NX_SAVEBUFFER);

    return success;
}

